
package com.studiofortress.sf.util.collections;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

/**
 *
 * @author Joseph Lenton - JosephLenton@StudioFortress.com
 */
public class CachingHashSet<E> implements Set<E>, CallbackIterable<E>
{
    // this is to state that the element is in the map
    private static final Object PRESENT = new Object();

    private final CachingHashMap<E, Object> innerMap;
    
    public CachingHashSet()
    {
        innerMap = new CachingHashMap();
    }

    public CachingHashSet(int initialCapacity)
    {
        innerMap = new CachingHashMap(initialCapacity);
    }
    
    public CachingHashSet(int initialCapacity, float loadFactor)
    {
        innerMap = new CachingHashMap(initialCapacity, loadFactor);
    }

    /**
     * Iterates over all of the elements in this list and for each value runs
     * the given callback.
     * @param callback The callback to run each element in this list against, cannot be null.
     */
    @Override
    public void iterate(CallbackIterator<E> callback)
    {
        innerMap.iterateKeys( callback );
    }

    @Override
    public void iteratePartial(CallbackPartialIterator<E> callback)
    {
        innerMap.iterateKeysPartial( callback );
    }
    
    public int size()
    {
        return innerMap.size();
    }

    public boolean isEmpty()
    {
        return innerMap.isEmpty();
    }

    public boolean contains(Object o)
    {
        return innerMap.containsKey( o );
    }

    public Iterator<E> iterator()
    {
        return innerMap.getKeyIterator();
    }
    
    public Object[] toArray()
    {
        return innerMap.keySet().toArray();
    }

    public <T> T[] toArray(T[] array)
    {
        return innerMap.keySet().toArray(array);
    }

    public boolean add(E e)
    {
        return innerMap.put(e, PRESENT) == null;
    }

    public boolean remove(Object o)
    {
        return innerMap.remove(o) == PRESENT;
    }

    public boolean containsAll(Collection<?> c)
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public boolean addAll(Collection<? extends E> c)
    {
        for (E e : c) {
            innerMap.put(e, PRESENT);
        }

        return c.size() > 0;
    }

    public boolean retainAll(Collection<?> c)
    {
        Set<E> keys = innerMap.keySet();
        keys.removeAll(c);
        return removeAll( keys );
    }
    
    public boolean removeAll(Collection<?> c)
    {
        for (Object e : c) {
            innerMap.remove( e );
        }

        return c.size() > 0;
    }

    public void clear()
    {
        innerMap.clear();
    }

    public void clearCache()
    {
        innerMap.clearCache();
    }

    public void clearFast()
    {
        innerMap.clearFast();
    }
}
